package net.jueb.sniff4j.extr.sendHandler;

import net.jueb.sniff4j.extr.base.AbstractRuntime;
import net.jueb.sniff4j.extr.filter.DefaultObjectFilter;
import net.jueb.sniff4j.socksCroe.SocksServerUtils;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;

/**
 * 代理服务器和目标主机间的数据处理
 * 将目标主机的返回数据发送到客户端通道
 * @author Administrator
 *
 */
public class SendToClientHandler extends ChannelInboundHandlerAdapter{
	protected static final InternalLogger log = InternalLoggerFactory.getInstance(SendToClientHandler.class);
	private Channel ClientChannel;
	private AbstractRuntime rt;
	public SendToClientHandler(Channel ClientChannel,AbstractRuntime rt) {
		this.ClientChannel=ClientChannel;
		this.rt=rt;
	}
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object response)
			throws Exception {
		if(response==null)
		{
			return;
		}
		//这里是回复数据过滤器
		//使用用户配置的过滤器
		DefaultObjectFilter filter=rt.getCurrentUser(ClientChannel).getSendToClientFilter(ctx.channel(),ClientChannel,rt);
		if(filter==null)
		{//使用server的过滤器
			filter=rt.getDefaultToClientFilter(ctx.channel(),ClientChannel);
		}
		Object obj=response;
		if(filter!=null)
		{
			obj=filter.doFilt(response);
		}
		if(obj==null)
		{//如果重构的消息为null，则表示被丢弃
			return;
		}
		if(ClientChannel.isActive()&&ClientChannel.isWritable()&&ClientChannel.isOpen())
		{
			ClientChannel.writeAndFlush(obj);
			log.debug("<<<<<<<<<<<<<<<<目标主机返回数据到客户端完毕<<<<<<<<<<<<<<<<");
		}else
		{
			ReferenceCountUtil.release(obj);
			log.debug("客户端关闭连接");
		}
	}
	
	 @Override
	 public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		if(ClientChannel.isActive())
		{
			SocksServerUtils.closeOnFlush(ClientChannel);
		}
	 }

	 @Override
	 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
	     ctx.close();
	     log.debug("主机:"+ctx.channel().remoteAddress()+":"+cause.getMessage());
	 }
}
